#if !defined(__DVC_COMMON_H__)
#define __DVC_COMMON_H__

#include "dvc_reg.h"

#define DVC_BAT_MAX_NUM 6
#define DVC_MAX_DATA_BYTE 8
#define DVC_ENABLE_LOG
#define DVC_ENABLE_EVENT_LOG

#pragma pack(1)


#ifdef DVC_ENABLE_LOG
/* 44Byte: 1分钟记录一次, 1天需要 63360Byte = 61.875KB */
/* 40Byte: 1分钟记录一次, 1天需要 57600Byte = 56.25KB */
/* 32Byte: 1分钟记录一次, 1天需要 46080Byte = 45KB  1小时记录一次, 1天需要 768B 1年需要 276480B = 270KB, 48K 可以存64天 48K 存一年数据 每天只可以存4条  */
/* 30Byte: 1分钟记录一次, 1天需要 43200Byte = 42.1875KB */
typedef struct dvc_log
{
    uint32_t timestamp;      /* 时间戳(s) */
    float voltage;           /* 总线电压(V) */
    float current;           /* 总线电流(A) */
    float power;             /* 总线功率(W) */
    uint16_t temp;           /* 温度 */
    uint16_t bat_voltage[6]; /* 电池电压 */
} dvc_log_t;
#endif

#define DVC_EVENT_TYPE_NONE 0             /* 无事件 */
#define DVC_EVENT_TYPE_CHG 1              /* 充电开关状态 */
#define DVC_EVENT_TYPE_DSG 2              /* 放电开关状态 */
#define DVC_EVENT_TYPE_OCD 3              /* 放电过流状态 */
#define DVC_EVENT_TYPE_SCD 4              /* 放电短路状态 */
#define DVC_EVENT_TYPE_UV 5               /* 电池欠压状态 */
#define DVC_EVENT_TYPE_OV 6               /* 电池过压状态 */
#define DVC_EVENT_TYPE_OCC 7              /* 充电过流状态 */
#define DVC_EVENT_TYPE_ALTER 8            /* 警报状态 */
#define DVC_EVENT_TYPE_CSST 9             /* 电流传感通异常状态 */
#define DVC_EVENT_TYPE_VSST 10            /* 电压传感通异常状态 */
#define DVC_EVENT_TYPE_LOAD 11            /* 负载接入状态 */
#define DVC_EVENT_TYPE_AE 12              /* 主动均衡开关状态 */
#define DVC_EVENT_TYPE_CLEAR_ALTER 13     /* 清除警报状态 */
#define DVC_EVENT_TYPE_UPDATE_USER_CFG 14 /* 更新用户配置 */
#define DVC_EVENT_TYPE_RESET 15           /* 复位芯片 */
#define DVC_EVENT_TYPE_SAVE_USER_CFG 16   /* 保存用户配置 */
#define DVC_EVENT_TYPE_GET_USER_CFG 17    /* 获取用户配置 */
#define DVC_EVENT_TYPE_AFE_CFG_ERR 18     /* AFE芯片配置不匹配 */
#define DVC_EVENT_TYPE_IO_ALTER 19        /* IO警报状态 */
#define DVC_EVENT_TYPE_REBOOT 20          /* 重启 */

#define DVC_EVENT_FLAG_AFE 0  /* 事件由AFE触发 */
#define DVC_EVENT_FLAG_USER 1 /* 事件由用户触发 */

#ifdef DVC_ENABLE_EVENT_LOG
/* 5字节 */
typedef struct dvc_log_event
{
    uint32_t timestamp; /* 时间戳(ms) */
    uint8_t event : 6;  /* 事件类型: 0-63 */
    uint8_t flag : 1;   /* 事件标志 */
    uint8_t state : 1;  /* 事件状态值 */
} dvc_log_event_t;
#endif

typedef enum
{
    BAT_TYPE_LI_ION,    /* 锂电池 */
    BAT_TYPE_LEAD_ACID, /* 铅酸 */
    BAT_TYPE_NI_MH,     /* 镍氢 */
    BAT_TYPE_LFP,       // 磷酸铁锂
    BAT_TYPE_UNKNOWN    /* 未知 */
} bat_type_t;

#define DVC_LOW_POWER_TYPE_DISABLE 0
#define DVC_LOW_POWER_TYPE_ENABLE 1
#define DVC_LOW_POWER_TYPE_DEEP_SLEEP 2

typedef struct dvc_ops
{
    /* SPI 写 */
    uint8_t (*write)(void *user_data, uint8_t *data, uint8_t len);
    /* SPI 读 */
    uint8_t (*read)(void *user_data, uint8_t *data, uint8_t len);
    /* SPI 写寄存器 */
    uint8_t (*write_reg)(void *user_data, uint32_t reg, uint8_t *data, uint8_t len);
    /* SPI 读寄存器 */
    uint8_t (*read_reg)(void *user_data, uint32_t reg, uint8_t *data, uint8_t len);
    /* 数据有更新, 数据上报 */
    void (*new_data)(void *dvc);
#if defined(DVC_ENABLE_LOG) || defined(DVC_ENABLE_EVENT_LOG)
    /* 日志/时间上报 */
    void (*log_push)(void *dvc, uint8_t type, void *log, void *event);
    /* 日志保存 */
    void (*save_log)(uint8_t *log, uint8_t is_event);
    /* 日志获取 */
    void (*get_logs)(void *dvc);
#endif
    void (*low_power)(void *user_data, uint8_t type);
    /* 保存用户配置 */
    uint8_t (*save_config)(void *user_data, const char *name, uint8_t *data, uint8_t len);
    /* 读取用户配置 */
    uint8_t (*get_config)(void *user_data, const char *name, uint8_t *data);
    /* 设置AES引脚电平 */
    void (*set_aes)(void *user_data, uint8_t state);
    /* 调用唤醒引脚 */
    void (*wakup)(void *user_data);
    /* 延迟指定毫秒 */
    void (*delay_ms)(uint16_t ms);
    float (*get_temp)(uint32_t temp_vol); /* 温度电压转换 */
    uint32_t (*get_time)(void);           /* 获取网络时间戳(秒级) */
    void *user_data;
} dvc_ops_t;

typedef enum dvc_tick_flag
{
    dvc_tick_flag_null = 0,
    dvc_tick_flag_256ms = (1 << 0),
    dvc_tick_flag_1s = (1 << 1),
    dvc_tick_flag_2s = (1 << 2),
    dvc_tick_flag_4s = (1 << 3),
    dvc_tick_flag_8s = (1 << 4),
    dvc_tick_flag_16s = (1 << 5),
    dvc_tick_flag_32s = (1 << 6),
    dvc_tick_flag_64s = (1 << 7),
} dvc_tick_flag_t;

typedef enum dvc_data_flag
{
    dvc_data_current_change = (1 << 0),
    dvc_data_voltage_change = (1 << 1),
    dvc_data_temp_change = (1 << 2),
} dvc_data_flag_t;

typedef struct dvc_calib
{
    float voltage; /* 总线电压校准倍数 */
    float current; /* 总线电流校准倍数 */
} dvc_calib_t;

typedef struct dvc_coulomb_counter_info
{
    float mA; /* 电流库仑计 */
    float mW; /* 功率库仑计 */
} dvc_coulomb_counter_t;

typedef struct dvc_user_cfg
{
    int32_t current_R; /* 电流检测电阻 uR */
    uint32_t bat_mAH;  /* 电池容量 mAh */
    struct
    {
        float max; /* 主动均衡开始电压 */
        float min; /* 主动均衡停止电压 */
    } aes;
    dvc_calib_t calib; /* 校准参数 */
    struct
    {
        uint8_t covt;        /* 电池#1 至电池#6 过压保护恢复阈值, 参考 dvc_ovt_t 枚举类型, 比 ovt 小 */
        uint8_t cuvt;        /* 电池#1 至电池#6 欠压保护恢复阈值, 参考 dvc_ovt_t 枚举类型, 比 uvt 大 */
        uint16_t cccd;       /* 充电/放电过流保护延时恢复(单位s) */
        uint16_t cscd;       /* 放电短路保护延时恢复(单位s) */
        uint8_t ovt;         /* 电池#1 至电池#6 过压保护阈值, 参考 dvc_ovt_t 枚举类型 */
        uint8_t uvt;         /* 电池#1 至电池#6 欠压保护阈值, 参考 dvc_uvt_t 枚举类型 */
        uint8_t occt : 4;    /* 充电过流保护阈值[mV]: 参考 dvc_occt_t 枚举类型 */
        uint8_t ocdt : 4;    /* 放电过流保护阈值[mV]: 参考 dvc_occt_t 枚举类型 */
        uint8_t ocdd : 3;    /* 放电过流保护延时[ms]: 参考 dvc_occd_t 枚举类型 */
        uint8_t occd : 3;    /* 充电过流保护延时[ms]: 参考 dvc_occd_t 枚举类型 */
        uint8_t scdd : 2;    /* 放电短路保护延时[us]: 参考 dvc_scdd_t 枚举类型 */
        uint8_t scdt : 4;    /* 放电短路保护阈值[mV]: 参考 dvc_scdt_t 枚举类型 */
        uint8_t cp_gc : 1;   /* 电流硬件保护检测倍率: 0 : 电流硬件保护检测倍率 X1  1 : 电流硬件保护检测倍率 X2 */
        uint8_t cs_pt : 3;   /* 电流传感通道轮询周期选择; 参考 : dvc_cs_vs_pt_t 枚举类型 */
        uint8_t vs_pt : 3;   /* 电压传感通道轮询周期选择; 参考 : dvc_cs_vs_pt_t 枚举类型 */
        uint8_t bat_num : 3; /* 实际使用的电池数量: max 6 */
        uint8_t invalid : 2; /* 未使用-占位 */
    } afe;
} dvc_user_cfg_t;

typedef struct dvc
{
    const dvc_ops_t *ops;       /* SPI通讯接口 和 复位控制 */
    dvc_user_cfg_t user_cfg;    /* 用户配置 */
    dvc_reg_cfg_t cfg;          /* 当前配置, 不建议用户修改 */
    dvc_reg_cfg_t w_cfg;        /* 等待写入的配置, 用户修改参数请修改此对象 */
    dvc_reg_status_t status;    /* 当前的状态 */
    dvc_reg_status_t r_status;  /* 等待处理的状态 */
    uint8_t tick_flag;          /* tick 标记 */
    uint32_t last_day;          /* 上一天 */
    uint32_t bat_num : 3;       /* 实际使用的电池数量: max 6 */
    uint32_t retry_count : 3;   /* 通讯失败时, 重发次数 */
    uint32_t in_read_check : 1; /* 位于 read_check 函数 */
    uint32_t io_alert : 1;      /* IO触发警报 */
    uint32_t alert : 1;         /* 触发警报 */
    uint32_t retry_num : 4;     /* 重复次数 */
    uint32_t change : 3;        /* 数据已改变 */
    uint32_t push : 1;          /* 需要上报数据 */
    uint32_t check_reg : 1;     /* 校验寄存器 */
    uint32_t read_cv : 1;       /* 读取电压电流信息 */
    uint32_t read_bat : 1;      /* 读取电池电压信息 */
    uint32_t read_temp : 1;     /* 读取温度信息 */
    uint32_t read_c : 1;        /* 运算库仑计信息 */
    uint32_t aes : 1;           /* 主动均衡开关状态 */
    uint32_t coulomb_count : 3; /* 库仑计累加次数 */
    uint32_t err_uv : 1;        /* 触发欠压 */
    uint32_t err_ov : 1;        /* 触发过压 */
    uint32_t err_alert : 1;     /* 触发警报 */
    uint32_t err_occ : 1;       /* 触发放电过流 */
    uint32_t push_aes_log : 1;  /* 新增一个均衡记录 */
    uint32_t aes_user : 1;      /* 用户设置的AES开关状态 */
    int32_t current_R;          /* 总线采样电阻 uΩ */
    uint16_t bat_totle_voltage; /* 电池总电压 */
    uint16_t bat_diff;          /* 电池压差 */
    uint16_t push_interval;     /* 数据上报间隔 */
#ifdef DVC_ENABLE_LOG
    uint16_t sec_tick; /* 监控 时钟 变量, 单位 s, 每天刷新 */
#endif
    uint32_t c_tick;           /* 上次计算容量的时间记录值 */
    uint32_t push_tick;        /* 上次数据上报的时间记录值 */
    uint32_t tick;             /* 监控 时钟 变量, 单位 ms */
    uint32_t ov_tick;          /* 过压触发时间 */
    uint32_t uv_tick;          /* 欠压触发时间 */
    uint32_t ccd_tick;         /* 充放电过流触发时间 */
    uint32_t scd_tick;         /* 放电短路触发时间 */
    uint32_t aes_tick;         /* 主动均衡触发时间 */
    uint32_t temp_vol;         /* 温度采样电压 mV */
    struct dvc_coulomb_counter /* 库仑计 */
    {
        dvc_coulomb_counter_t sec; /* 上1秒库仑计的均值 */
        dvc_coulomb_counter_t chg; /* 库仑计每日充电累加,单位S(每日清空) */
        dvc_coulomb_counter_t dsg; /* 库仑计每日放电累加,单位S(每日清空) */
        dvc_coulomb_counter_t sum; /* 总库仑计每日累加, */
        float bat_mA;              /* 电池电流总容量 */
        float bat_rmA;             /* 电池剩余电流容量 */
        float bat_health;          /* 电池健康度 0~1 */
        uint32_t bat_rtime;        /* 剩余可用时间 */
    } coulomb_counter;             /* 库仑计 */
    dvc_calib_t calib;
    /* 上报数据 */
    float voltage;       /* 总线电压 V */
    float current;       /* 总线电流 A */
    float power;         /* 总线功率 W */
    float mcu_temp;      /* 芯片内部温度 */
    float temp;          /* 外部采样温度 (mV/℃) */
    uint16_t bat_vol[6]; /* 电池电压 uV */
#if defined(DVC_ENABLE_LOG) || defined(DVC_ENABLE_EVENT_LOG)
    struct
    {
#if defined(DVC_ENABLE_LOG)
        dvc_log_t sec[60];    /* 每秒均值记录, 只记录一分钟 */
        dvc_log_t min[60];    /* 每分钟均值记录, 只记录一小时 */
        dvc_log_t hour[24];   /* 每小时均值记录, 只记录一天 */
        dvc_log_t day[1440];  /* 1天内的每分钟的均值记录 */
        dvc_log_t years[366]; /* 一年内的每天均值 */
        uint16_t years_w;     /* 写指针 */
#endif
#if defined(DVC_ENABLE_EVENT_LOG)
        dvc_log_event_t event[1440]; /* 事件记录 7K */
        uint16_t event_w;            /* 写指针 */
#endif
    } log;
#endif
} dvc_s, *dvc_t;
#pragma pack()

#define DVC_DEFAULT_USER_CFG                  \
    {                                         \
        .current_R = 1000,                    \
        .bat_mAH = 20000,                     \
        .aes = {                              \
            .max = 0.05,                      \
            .min = 0.005,                     \
        },                                    \
        .calib = {                            \
            .voltage = 1.0,                   \
            .current = 1.0,                   \
        },                                    \
        .afe = {                              \
            .covt = dvc_ovt_3_451V,           \
            .cuvt = dvc_uvt_3_105V,           \
            .cccd = 30,                       \
            .cscd = 5,                        \
            .ovt = dvc_ovt_3_609V,            \
            .uvt = dvc_uvt_2_947V,            \
            .occt = dvc_occt_2_3mv,           \
            .ocdt = dvc_occt_2_3mv,           \
            .ocdd = dvc_occd_32ms,            \
            .occd = dvc_occd_32ms,            \
            .scdd = dvc_scdd_400us,           \
            .scdt = dvc_occt_9_7mv,           \
            .cp_gc = 1,                       \
            .cs_pt = dvc_cs_vs_pt_continuous, \
            .vs_pt = dvc_cs_vs_pt_continuous, \
            .bat_num = 4,                     \
        }                                     \
    }

#define DVC_DEFAULT_CFG_0                                                                                      \
    {                                                                                                          \
        .chg_en = 1,                      /* 充电开启 */                                                       \
        .dsg_en = 1,                      /* 放电开启 */                                                       \
        .vref_vs = 1,                     /* 3.3V */                                                           \
        .vout_vs = 1,                     /* 3.3V */                                                           \
        .vout_en = 1,                     /* 开启VOUT输出 */                                                   \
        .cp_en = 1,                       /* 电流硬件保护使能 */                                               \
        .cs_en = 1,                       /* 电流传感通道使能 */                                               \
        .vs_en = 1,                       /* 电压传感通道使能 */                                               \
        .cb1 = 0,                         /* 第 1 节电池被动均衡驱动器不使能 */                                \
        .cb2 = 0,                         /* 第 2 节电池被动均衡驱动器不使能 */                                \
        .cb3 = 0,                         /* 第 3 节电池被动均衡驱动器不使能 */                                \
        .cb4 = 0,                         /* 第 4 节电池被动均衡驱动器不使能 */                                \
        .cb5 = 0,                         /* 第 5 节电池被动均衡驱动器不使能 */                                \
        .cb6 = 0,                         /* 第 6 节电池被动均衡驱动器不使能 */                                \
        .cs_pt = dvc_cs_vs_pt_continuous, /* 电流传感通道轮询周期选择: 连续模式*/                              \
        .vs_pt = dvc_cs_vs_pt_continuous, /* 电流传感通道轮询周期选择: 连续模式*/                              \
        .ld_en = dvc_ld_en_enable,        /* 负载检测使能: 负载检测开启*/                                      \
        .vrm = dvc_vrm_auto,              /* VREF 工作模式: 自动模式*/                                         \
        .wdm = dvc_apm_reset_vout,        /* 看门狗超时后反复重启 VOUT 输出*/                                  \
        .apm = dvc_apm_disable,           /* 警报下拉检测关闭*/                                                \
        .dsg_ocd = 0,                     /* 当检测到放电过流警报时，强制关闭放电管驱动输出 */                 \
        .dsg_scd = 0,                     /* 当检测到放电短路警报时，强制关闭放电管驱动输出 */                 \
        .dsg_uv = 0,                      /* 当检测到电池#1 至电池#6 出现欠压警报时，强制关闭放电管驱动输出 */ \
        .dsg_ov = 1,                      /* 当检测到电池#1 至电池#6 出现过压警报时，不关闭放电管驱动输出 */   \
        .dsg_alt = 0,                     /* 当检测到警报下拉时，强制关闭放电管驱动输出 */                     \
        .dsg_cs = 0,                      /* 当电流传感通道进入故障模式时，强制关闭放电管驱动输出 */           \
        .dsg_vs = 0,                      /* 当电压传感通道进入故障模式时，强制关闭放电管驱动输出 */           \
        .dsg_occ = 0,                     /* 当检测到充电过流警报时，强制关闭放电管驱动输出 */                 \
        .chg_ocd = 0,                     /* 当检测到放电过流警报时，强制关闭充电管驱动输出 */                 \
        .chg_scd = 0,                     /* 当检测到放电短路警报时，强制关闭充电管驱动输出 */                 \
        .chg_uv = 1,                      /* 当检测到电池#1 至电池#6 出现欠压警报时，不关闭充电管驱动输出 */   \
        .chg_ov = 0,                      /* 当检测到电池#1 至电池#6 出现过压警报时，强制关闭充电管驱动输出 */ \
        .chg_alt = 0,                     /* 当检测到警报下拉时，强制关闭充电管驱动输出 */                     \
        .chg_cs = 0,                      /* 当电流传感通道进入故障模式时，强制关闭充电管驱动输出 */           \
        .chg_vs = 0,                      /* 当电压传感通道进入故障模式时，强制关闭充电管驱动输出 */           \
        .chg_occ = 0,                     /* 当检测到充电过流警报时，强制关闭充电管驱动输出 */                 \
    }

#define DVC_DEFAULT_CFG_1                                                                   \
    {                                                                                       \
        .ovt = dvc_ovt_3_609V,  /* 电池#1 至电池#6 过压保护阈值, 参考 dvc_ovt_t 枚举类型 */ \
        .uvt = dvc_uvt_2_947V,  /* 电池#1 至电池#6 欠压保护阈值, 参考 dvc_uvt_t 枚举类型 */ \
        .occt = dvc_occt_2_3mv, /* 充电过流保护阈值[mV] */                                  \
        .ocdt = dvc_occt_2_3mv, /* 放电过流保护阈值[mV] */                                  \
        .ocdd = dvc_occd_32ms,  /* 放电过流保护延时[ms] */                                  \
        .occd = dvc_occd_32ms,  /* 充电过流保护延时[ms] */                                  \
        .scdd = dvc_scdd_400us, /* 放电短路保护延时[us] */                                  \
        .scdt = dvc_occt_9_7mv, /* 放电短路保护阈值[mV] */                                  \
        .cp_gc = 1,             /* 电流硬件保护检测倍率 X2 */                               \
        .cadc_tm = 1,           /* CADC 电流采样时间选择[ms]: 0 : 64ms | 1 : 256ms */       \
    }

#endif // __DVC_COMMON_H__
